package com.qg.wcsopcuaqj.taskPool;


import com.qg.wcsopcuaqj.business.entity.TWcsRgvAlarm;
import com.qg.wcsopcuaqj.business.service.ITWcsRgvAlarmService;
import com.qg.wcsopcuaqj.dispatch.configuration.InitialHeartBeat;
import com.qg.wcsopcuaqj.dispatch.constant.QGSConstant;
import com.qg.wcsopcuaqj.enums.rgv1.RGV1Plc2WcsVarEnum;
import com.qg.wcsopcuaqj.enums.rgv1.RGV1Wcs2PlcVarEnum;
import com.qg.wcsopcuaqj.opcua.selfunion.Enum.PLCType;
import com.qg.wcsopcuaqj.opcua.selfunion.UAService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.UUID;

/**
 * @Author: 蔡翔
 * @Date: 2019/10/30 16:23
 * @Version 1.0
 *
 *
 * //会检测RGV1 / RGV2 / 窑炉 心跳状态；如果 心跳检测异常大于等于3次，就断开心跳连接
 */
public class RGVHeartRunnable implements Runnable {
    private final static Logger logger = LoggerFactory.getLogger(RGVHeartRunnable.class);
    private UAService uaService;
    private ITWcsRgvAlarmService alarmService;
    private Integer count = 0;
    private Integer plcHealthyCount = 0;
    private String heartBeatName;

    public RGVHeartRunnable(UAService uaService, ITWcsRgvAlarmService alarmService){
        this.uaService = uaService;
        this.alarmService = alarmService;
        heartBeatName = "此次连接心跳标识: "+UUID.randomUUID().toString();
    }

    public RGVHeartRunnable(){

    }

    @Override
    public void run() {
        Boolean initialVlue = false;
        Boolean aBoolean= null;
        while(true){
            try {
                //todo 修改heart 变量地址。
                Thread.sleep(2000);
                Boolean rgv1Before = Boolean.valueOf(getValue(RGV1Wcs2PlcVarEnum.RGV1));
                Date rgv1time = new Date();
                Boolean rgv2Before = Boolean.valueOf(getValue(RGV1Wcs2PlcVarEnum.RGV2));
                Boolean ipsenBefore = Boolean.valueOf(getValue(RGV1Wcs2PlcVarEnum.Ipsen));

                Thread.sleep(2000);

                Boolean rgv1After = Boolean.valueOf(getValue(RGV1Wcs2PlcVarEnum.RGV1));
                Date rgv1time2 = new Date();
                Boolean rgv2After = Boolean.valueOf(getValue(RGV1Wcs2PlcVarEnum.RGV2));
                Boolean ipsenAfter = Boolean.valueOf(getValue(RGV1Wcs2PlcVarEnum.Ipsen));

                if(rgv1Before.equals(rgv1After)){
                    alarmCreate("RGV1 网络断开连接，wcs与plc 网络连接 出现异常 尝试连接次数: "+count+", plc 与总plc断连次数: "+plcHealthyCount+" ;; rgv1Before:"+rgv1Before+" , time: "+rgv1time.toString()+" , rgv1After"+rgv1After+", time2:"+rgv1time2.toString());
                    plcHealthyCount++;
                    logger.info("RGV1 网络断开连接，wcs与plc 网络连接 出现异常 尝试连接次数: "+count+", plc 与总plc断连次数: "+plcHealthyCount+" ;; rgv1Before:"+rgv1Before+" , time: "+rgv1time.toString()+" , rgv1After"+rgv1After+", time2:"+rgv1time2.toString());
                }else if(rgv2Before.equals(rgv2After)){
                    alarmCreate("RGV2 网络断开连接，wcs与plc 网络连接 出现异常 尝试连接次数: "+count+", plc 与总plc断连次数: "+plcHealthyCount+";; rgv2Before:"+rgv2Before+" , time: "+rgv1time.toString()+",rgv2After"+rgv2After+", time2:"+rgv1time2.toString());
                    plcHealthyCount++;
                    logger.info("RGVHeartRunnable.  setValue 出现异常，setValue Status:"+aBoolean+"; 尝试连接次数: "+count+", plc 与总plc断连次数: "+plcHealthyCount+";; rgv2Before:"+rgv2Before+" , time: "+rgv1time.toString()+",rgv2After"+rgv2After+", time2:"+rgv1time2.toString());
                }else if(ipsenBefore.equals(ipsenAfter)){
                    alarmCreate("窑炉 网络断开连接，wcs与plc 网络连接 出现异常 尝试连接次数: "+count+", plc 与总plc断连次数: "+plcHealthyCount+";; ipsenBefore:"+ipsenBefore+" , time: "+rgv1time.toString()+",ipsenAfter"+ipsenAfter+", time2:"+rgv1time2.toString());
                    plcHealthyCount++;
                    logger.info("RGVHeartRunnable.  setValue 出现异常，setValue Status:"+aBoolean+"; 尝试连接次数: "+count+", plc 与总plc断连次数: "+plcHealthyCount+";; ipsenBefore:"+ipsenBefore+" , time: "+rgv1time.toString()+",ipsenAfter"+ipsenAfter+", time2:"+rgv1time2.toString());
                }else {
                    InitialHeartBeat.setConnectStatus(true);
                    plcHealthyCount = 0;
                    count = 0;
                }

                if(plcHealthyCount>=3){
                    alarmCreate("网络断开连接，wcs与plc 出现异常, 重连3次失败。 现在退出心跳检测。。。");
                    InitialHeartBeat.setConnectStatus(false);
                    logger.info("RGVHeartRunnable.  plc与总PLC 连接出现异常， 尝试连接次数用尽，现在退出心跳检测");
                    break;
                }
            } catch (Exception e) {
                alarmCreate("WCS 网络断开连接，wcs与plc 网络连接 出现异常");
                count++;
                if(count>=3){
                    alarmCreate("网络断开连接，wcs与plc 出现异常, 重连3次失败。 现在退出心跳检测。。。");
                    InitialHeartBeat.setConnectStatus(false);
                    logger.info("RGVHeartRunnable.  setValue 出现异常，setValue Status:"+aBoolean+"; 尝试连接次数用尽，现在退出心跳检测");
                    break;
                }
                logger.info("RGVHeartRunnable.  setValue 出现异常，setValue Status:"+aBoolean+"; 尝试连接次数: "+count);
            }
        }
    }


    private void alarmCreate(String alarmText){
        //发出报警
        TWcsRgvAlarm alarm = new TWcsRgvAlarm();
        alarm.setAlarmInfo(alarmText);
        alarm.setIsTaskfinished(-1);
        alarm.setRgvName("-1");
        alarm.setIsSendfinished(-1);
        alarm.setHasGoods(-1);
        alarm.setIsPickfinished(-1);
        alarm.setTaskno(heartBeatName);
        alarm.setCreateTime(LocalDateTime.now());
        alarm.setUpdateTime(LocalDateTime.now());
        alarmService.getBaseMapper().insert(alarm);
    }

    private String getValue(RGV1Plc2WcsVarEnum var) throws Exception {
        return uaService.getValue(var.getNamespace(), var.getIdentity(), QGSConstant.plcName).getValue().getValue().toString();
    }
    private String getValue(RGV1Wcs2PlcVarEnum var) throws Exception {
        return uaService.getValue(var.getNamespace(), var.getIdentity(), QGSConstant.plcName).getValue().getValue().toString();
    }


    private Boolean setValue(RGV1Wcs2PlcVarEnum var,String dataType,Object newValue) throws Exception {
        return uaService.setValue(
                var.getNamespace(),
                var.getIdentity(),
                PLCType.valueOf(dataType).convertType(newValue),
                QGSConstant.plcName);
    }
    private Boolean setValue(RGV1Plc2WcsVarEnum var,String dataType,Object newValue) throws Exception {
        return uaService.setValue(
                var.getNamespace(),
                var.getIdentity(),
                PLCType.valueOf(dataType).convertType(newValue),
                QGSConstant.plcName
        );
    }


}
